package sk.tonyb.crawler.storage;

import java.util.ArrayList;
import java.util.List;

import sk.tonyb.library.collection.ListProcessor;

/** 
 * Class, which store values used by web crawler. <br>
 * All methods of this class are synchronized. 
 *  
 * @author Anton Balucha
 * @since 12.12.2011
 * @last_modified 14.12.2011
 */
public class CrawlerLocalStorage implements ICrawlerStorage {
	
	private static volatile CrawlerLocalStorage crawlerLocalStorage = null;
	
	private volatile List<String> listOfUnprocessedLinks = null;
	private volatile List<String> listOfProcessedLinks = null;

	/** Constructor. */
	public CrawlerLocalStorage() {
		this.init();
	}
	
	/** Method, which return same intance of {@link CrawlerLocalStorage} - singleton. */
	public static synchronized CrawlerLocalStorage getInstance() {
		
		if(CrawlerLocalStorage.crawlerLocalStorage == null) {
			CrawlerLocalStorage.crawlerLocalStorage = new CrawlerLocalStorage();
		}
		
		return CrawlerLocalStorage.crawlerLocalStorage;
	}
	
	/** Initialization of lists. */
	private synchronized void init() {
		this.listOfUnprocessedLinks = new ArrayList<String>();
		this.listOfProcessedLinks = new ArrayList<String>();
	}
	
	/** Method return copy of list, which store unprocessed links. */
	@Override
	public synchronized List<String> getListOdUnprocessedLinks() {
		return new ListProcessor().copy(this.listOfUnprocessedLinks);
	}
	
	/** Method return copy of list, which store processed links. */
	@Override
	public synchronized List<String> getListOdProcessedLinks() {
		return new ListProcessor().copy(this.listOfProcessedLinks);
	}

	/** Method, which insert link into list of unprocessed links. */
	@Override
	public synchronized void insertLink(String link) {
		
		if(link != null && this.listOfUnprocessedLinks.contains(link.trim()) == false) {
			this.listOfUnprocessedLinks.add(link.trim());
		}
	}
	
	/** Method, which insert list of links into unprocessed list of links. */
	@Override
	public synchronized void insertLinks(String[] links) {
		
		if(links != null && links.length > 0) {
			
			for(int i = 0; i < links.length; i++) {

				if(links[i] != null && links[i].trim().isEmpty() == false) {
					this.listOfUnprocessedLinks.add(links[i].trim());
				}
			}
		}
	}
	
	/** 
	 * Method, which return link from list of unprocessed links. <br>
	 * After that, this link will be marked as processed. <br>
	 * 
	 * @return 
	 * link - link to process. <br>
	 * null - if no link exists or some error occurs. <br>
	 */
	@Override
	public synchronized String getLinkToProcess() {
		
		String link = null;
		
		if(this.listOfUnprocessedLinks.size() > 0) {
			
			link = this.listOfUnprocessedLinks.get(0);
			this.listOfUnprocessedLinks.remove(0);
			this.listOfProcessedLinks.add(link);
		}
		
		return link;
	}
	
	/** 
	 * Method, which check if link is not processed. <br>
	 * 
	 * @param link - link, which will be verified if is unprocessed. <br>
	 * @return
	 * true - link is unprocessed. <br>
	 * false - it was not possible to verify, if link is unprocessed. <br>
	 */
	@Override
	public synchronized boolean isUnprocessedLink(String link) {
		
		if(link != null && link.trim().isEmpty() == false && this.listOfUnprocessedLinks.contains(link)) {
			return true;
		}
		
		else {
			return false;
		}
	}
	
	/** 
	 * Method, which verify, if link is processed. <br>
	 * 
	 * @param link - link, which will be verified. <br>
	 * @return
	 * true - link already was processed. <br>
	 * false - it was no possible to verify, if link is unprocessed. <br>
	 */
	@Override
	public synchronized boolean isProcessedLink(String link) {
		
		if(link != null && link.trim().isEmpty() == false && this.listOfProcessedLinks.contains(link)) {
			return true;
		}
		
		else {
			return false;
		}
	}	
}
